/**
 * 
 */
package arch.bus;

import java.util.Observable;

import util.SysHelper;

import arch.cpu.Alu;
import arch.cpu.Execute;
import arch.cpu.RegisterGroup;
import arch.mem.MemoryControl;

/**
 * @author petery
 *
 */
public class SystemBus extends Observable
{
	public enum BusDataType{Register, IMem, DMem, Ctrl, Alu};
	
	private Alu alu;
	private RegisterGroup regGroup;
	private MemoryControl memCtrl;
	private Execute execution;
	
	public SystemBus()
	{

	}
	
	public void setComponet(Alu alu, RegisterGroup regs, MemoryControl mems, Execute exec)
	{
		this.alu = alu;
		this.regGroup = regs;
		this.memCtrl = mems;
		this.execution = exec;
	}
	
	public void set(BusDataType dataType, Object location, Object data)
	{
		switch(dataType)
		{
			case Register:
				// TODO: need a common interface here for data/pc/ZF in reg
				this.regGroup.set(
						Integer.parseInt(location.toString()), 
						Integer.parseInt(data.toString()));
				break;
				
			case IMem:
				this.memCtrl.iset(
						Integer.parseInt(location.toString()), 
						data.toString());
				break;
				
			case DMem:
				this.memCtrl.set(
						Integer.parseInt(location.toString()),
						Integer.parseInt(data.toString()));
				break;
				
			case Alu:
				Object[] ds = (Object[])data;
				int a = Integer.parseInt(ds[0].toString());
				int b = Integer.parseInt(ds[1].toString());
				this.alu.set(location.toString(), a, b);
				break;
				
			case Ctrl:
				
				break;
		}
		notifyUI(dataType, true);
		SysHelper.sleep();
		notifyUI(dataType, false);
	}
	
	public Object get(BusDataType dataType, Object location)
	{
		Object res = null;
		switch(dataType)
		{
			case Register:
				// TODO: need a common interface here for data/pc/ZF in reg
				res = this.regGroup.get(Integer.parseInt(location.toString()));
				break;
				
			case IMem:
				res = this.memCtrl.iget(Integer.parseInt(location.toString()));
				break;
				
			case DMem:
				res = this.memCtrl.get(Integer.parseInt(location.toString()));
				break;
				
			case Alu:
				res = this.alu.get();
				break;
				
			case Ctrl:
				
				break;
		}
		notifyUI(dataType, true);
		SysHelper.sleep();
		notifyUI(dataType, false);
		return res;
	}
	
	private void notifyUI(BusDataType dataType, boolean value)
	{
		this.setChanged();
		this.notifyObservers(new Object[]{dataType, value});
	}
}
